/***************************************************************************
 * *  FILENAME: draw_wave.c
 * *  DESCRIPTION:  
 * *    Called by mpi_wave routines to draw a graph of results
 * *  AUTHOR: Blaise Barney
 * *  LAST REVISED: 07/12/06
 * ***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

#define HEIGHT         500 
#define WIDTH          1000

typedef struct {
				Window window;
				XSizeHints hints;
				XColor backcolor;
				XColor bordcolor;
				int    bordwidth;
} MYWINDOW;

char baseword[] = {"draw_wave"},
		 exitword[] = {"Exit"},
		 text[10];

/* Note extra underscore in draw_wave routine - needed for Fortran */
void draw_wave_(double * results) {

				float 	scale, point, coloratio = 65535.0 / 255.0;
				int 	i,j,k,y, zeroaxis, done, myscreen, points[WIDTH];

				MYWINDOW base, quit;
				Font 	font,font2;   
				GC 		itemgc,textgc,pointgc,linegc; 
				XColor 	red,yellow,blue,green,black,white;
				XEvent 	myevent;
				Colormap cmap;
				KeySym 	mykey;
				Display *mydisp;


				/* Set rgb values for colors */
				red.red= (int) (255 * coloratio);
				red.green= (int) (0 * coloratio);
				red.blue = (int) (0 * coloratio);

				yellow.red= (int) (255 * coloratio);
				yellow.green= (int) (255 * coloratio);
				yellow.blue= (int) (0 * coloratio);

				blue.red= (int) (0 * coloratio);
				blue.green= (int) (0 * coloratio);
				blue.blue= (int) (255 * coloratio);

				green.red= (int) (0 * coloratio);
				green.green= (int) (255 * coloratio);
				green.blue= (int) (0 * coloratio);

				black.red= (int) (0 * coloratio);
				black.green= (int) (0 * coloratio);
				black.blue= (int) (0 * coloratio);

				white.red= (int) (255 * coloratio);
				white.green= (int) (255 * coloratio);
				white.blue= (int) (255 * coloratio);

				mydisp = XOpenDisplay("");
				if (!mydisp) {
								fprintf (stderr, "Hey! Either you don't have X or something's not right.\n");
								fprintf (stderr, "Guess I won't be showing the graph.  No big deal.\n");
								exit(1);
				}
				myscreen = DefaultScreen(mydisp);
				cmap = DefaultColormap (mydisp, myscreen);
				XAllocColor (mydisp, cmap, &red); 
				XAllocColor (mydisp, cmap, &yellow);
				XAllocColor (mydisp, cmap, &blue);
				XAllocColor (mydisp, cmap, &black); 
				XAllocColor (mydisp, cmap, &green); 
				XAllocColor (mydisp, cmap, &white); 

				/* Set up for creating the windows */
				/* XCreateSimpleWindow uses defaults for many attributes,   */
				/* thereby simplifying the programmer's work in many cases. */

				/* base window position and size */
				base.hints.x = 50;
				base.hints.y = 50;
				base.hints.width = WIDTH;
				base.hints.height = HEIGHT;
				base.hints.flags = PPosition | PSize;
				base.bordwidth = 5;

				/* window Creation */
				/* base window */
				base.window = XCreateSimpleWindow (mydisp, DefaultRootWindow (mydisp), 
												base.hints.x, base.hints.y, base.hints.width, 
												base.hints.height, base.bordwidth, black.pixel,
												black.pixel);
				XSetStandardProperties (mydisp, base.window, baseword, baseword, None,
												NULL, 0, &base.hints);

				/* quit window position and size (subwindow of base) */
				quit.hints.x = 5;
				quit.hints.y = 450;
				quit.hints.width = 70;
				quit.hints.height = 30;
				quit.hints.flags = PPosition | PSize;
				quit.bordwidth = 5;

				quit.window = XCreateSimpleWindow (mydisp, base.window, quit.hints.x, 
												quit.hints.y, quit.hints.width, quit.hints.height,
												quit.bordwidth, green.pixel, yellow.pixel);
				XSetStandardProperties (mydisp, quit.window, exitword, exitword, None,
												NULL, 0, &quit.hints);

				/* Load fonts */
				/*
				 * font = XLoadFont (mydisp, "Rom28");
				 * font2 = XLoadFont (mydisp, "Rom17.500");
				 * */
				font = XLoadFont (mydisp, "fixed");
				font2 = XLoadFont (mydisp, "fixed");

				/* GC creation and initialization */
				textgc = XCreateGC (mydisp, base.window, 0,0);
				XSetFont (mydisp, textgc, font);
				XSetForeground (mydisp, textgc, white.pixel);

				linegc = XCreateGC (mydisp, base.window, 0,0);
				XSetForeground (mydisp, linegc, white.pixel);

				itemgc = XCreateGC (mydisp, quit.window, 0,0);
				XSetFont (mydisp, itemgc, font2);
				XSetForeground (mydisp, itemgc, black.pixel);

				pointgc = XCreateGC (mydisp, base.window, 0,0);
				XSetForeground (mydisp, pointgc, green.pixel);

				/* The program is event driven; the XSelectInput call sets which */
				/* kinds of interrupts are desired for each window.              */
				/* These aren't all used. */
				XSelectInput (mydisp, base.window,
												ButtonPressMask | KeyPressMask | ExposureMask);
				XSelectInput (mydisp, quit.window,
												ButtonPressMask | KeyPressMask | ExposureMask);

				/* window mapping -- this lets windows be displayed */
				XMapRaised (mydisp, base.window);
				XMapSubwindows (mydisp, base.window);

				/* Scale each data point  */
				zeroaxis = HEIGHT/2;
				scale = (float)zeroaxis;
				for(j=0;j<WIDTH;j++) 
								points[j]  = zeroaxis - (int)(results[j] * scale);

				/* Main event loop  --  exits when user clicks on "exit" */
				done = 0;
				while (! done) {
								XNextEvent (mydisp, &myevent);   /* Read next event */
								switch (myevent.type) {
												case Expose:
																if (myevent.xexpose.count == 0) {
																				if (myevent.xexpose.window == base.window) {
																								XDrawString (mydisp, base.window, textgc, 775, 30, "Wave",4);
																								XDrawLine (mydisp, base.window, linegc, 1,zeroaxis,WIDTH,
																																zeroaxis);
																								for (j=1; j<WIDTH; j++) 
																												XDrawPoint (mydisp, base.window, pointgc, j, points[j-1]);
																				}

																				else if (myevent.xexpose.window == quit.window) {
																								XDrawString (mydisp, quit.window, itemgc, 12,20, exitword, 
																																strlen(exitword));
																				}
																}   /* case Expose */
																break;

												case ButtonPress:
																if (myevent.xbutton.window == quit.window)
																				done = 1;
																break;

												case KeyPress:
																/*
																 *       i = XLookupString (&myevent, text, 10, &mykey, 0);
																 *             if (i == 1 && text[0] == 'q')
																 *                      done = 1;
																 *                      */
																break;

												case MappingNotify:
																/*
																 *       XRefreshKeyboardMapping (&myevent);
																 *       */
																break;

								}  /* switch (myevent.type) */

				}   /* while (! done) */

				XDestroyWindow (mydisp, base.window);
				XCloseDisplay (mydisp);
}

